package com.handle.gateway.handler;

import com.handle.common.core.exception.ValidateException;
import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler;
import org.springframework.boot.web.error.ErrorAttributeOptions;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpStatus;
import org.springframework.web.reactive.function.server.*;
import org.springframework.web.server.ResponseStatusException;

import java.util.HashMap;
import java.util.Map;

/**
 * @author zhangqing
 * @version V1.0
 * @description 网关拦截器json异常处理器
 * @date 8/12/2020 5:00 PM
 */
public class JsonExceptionHandler extends DefaultErrorWebExceptionHandler {
    public JsonExceptionHandler(ErrorAttributes errorAttributes, ResourceProperties resourceProperties, ErrorProperties errorProperties, ApplicationContext applicationContext) {
        super(errorAttributes, resourceProperties, errorProperties, applicationContext);
    }

    /**
     *
     * @param request 请求
     * @param options 包括堆栈跟踪
     * @return map
     */
    @Override
    protected Map<String, Object> getErrorAttributes(ServerRequest request, ErrorAttributeOptions options) {
        int code =500;
        Throwable error = super.getError(request);
        String message=error.getMessage();
        if (error instanceof ValidateException) {
            code = HttpStatus.PRECONDITION_FAILED.value();
        } else {
//            code = ((ResponseStatusException) error).getStatus().value();
        }
        return response(code, message);
    }

    /**
     * 指定响应处理方法为JSON处理的方法
     *
     * @param errorAttributes 提供对错误属性的访问，这些错误属性可以被记录或显示给用户。
     */
    @Override
    protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
        return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
    }

    /**
     * 根据code获取对应的HttpStatus
     * @param errorAttributes
     */
    @Override
    protected int getHttpStatus(Map<String, Object> errorAttributes) {
        return  (int) errorAttributes.get("code");
    }


    /**
     * 构建返回的JSON数据格式
     *
     * @param status       状态码
     * @param errorMessage 异常信息
     * @return map
     */
    private static Map<String, Object> response(int status, String errorMessage) {
        Map<String, Object> map = new HashMap<>(16);
        map.put("code", status);
        map.put("message", errorMessage);
        return map;
    }
}
